﻿#include <Windows.h>
#include <DbgHelp.h>
#include <stdio.h>

#pragma comment (lib, "DbgHelp.lib")

// Number of addresses to read
#define ADDRESSES_LENGTH 8

#ifdef __cplusplus
EXTERN_C{
#endif

extern BOOL GrabRetAddresses(LPVOID * pResult, DWORD dwSize);

#ifdef __cplusplus
}
#endif

BOOL g_bSymInitialized = FALSE;

/*
	函数声明
	（若无函数声明，则函数必须按顺序实现）
*/ 

PCHAR FuncNameByAddr(LPVOID lpFuncAddr);
void TraceCalls();
void funcC();

/*
	函数实现
*/

// 打印调用栈
void TraceCalls() {
	PCHAR cpName;
	LPVOID lpAddresses[ADDRESSES_LENGTH] = { 0 };

	if (!GrabRetAddresses(lpAddresses, ADDRESSES_LENGTH))
	{
		puts("Failed to grab ret addresses");
		return;
	}

	for (int nIdx = 0; nIdx < ADDRESSES_LENGTH; nIdx++)
	{
		printf("Return Addr = %p, Function Name = ", lpAddresses[nIdx]);

		if (cpName = FuncNameByAddr(lpAddresses[nIdx]))
		{
			printf("%s\n", cpName);
			free(cpName);
		}
		else {
			puts("UNKNOWN");
		}
	}
}

PCHAR FuncNameByAddr(LPVOID lpFuncAddr)
{
	PSYMBOL_INFO pSymbol;
	PCHAR cpName;
	HANDLE hCurrProc = GetCurrentProcess();
	DWORD64 dw64Displacement = 0;
	DWORD dwSize = sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR);
	DWORD dwNameSize = MAX_SYM_NAME * sizeof(TCHAR);

	if (!g_bSymInitialized)
	{
		if (!SymInitialize(hCurrProc, NULL, TRUE))
			return NULL;

		g_bSymInitialized = TRUE;
	}

	if (!(pSymbol = (PSYMBOL_INFO)malloc(dwSize)))
		return NULL;

	ZeroMemory(pSymbol, dwSize);
	pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
	pSymbol->MaxNameLen = MAX_SYM_NAME;


	if (!SymFromAddr(hCurrProc, (DWORD64)lpFuncAddr, &dw64Displacement, pSymbol))
	{
		free(pSymbol);
		return NULL;
	}

	if (!(cpName = (PCHAR)malloc(dwNameSize)))
	{
		free(pSymbol);
		return NULL;
	}

	UnDecorateSymbolName(pSymbol->Name, (PSTR)cpName, dwNameSize, UNDNAME_COMPLETE);
	free(pSymbol);

	return cpName;
}

void funcC() {
	puts("Hello from funcC");
	TraceCalls();
}

int main() {
	funcC();
	return 0;
}